package ace.module.oauth2.server.core.impl.authentication.ace.factory.impl;

import ace.cmp.spring.util.core.SpringUtils;
import ace.module.oauth2.server.api.callback.Oauth2AceAuthenticationCallbackApi;
import ace.module.oauth2.server.api.callback.Oauth2AceAuthorizationCallbackApi;
import ace.module.oauth2.server.api.enums.Oauth2RegisteredClientAuthConfigApiImplTypeEnum;
import ace.module.oauth2.server.core.impl.authentication.ace.factory.CallbackApiBeanFactory;
import ace.module.oauth2.server.core.impl.dao.entity.Oauth2RegisteredClientAuthConfig;
import lombok.AllArgsConstructor;
import lombok.extern.log4j.Log4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;
import org.springframework.util.Assert;

/**
 * 认证实现接口工厂.
 *
 * @author caspar
 */
@Log4j
@AllArgsConstructor
@Component
public class CallbackApiBeanFactoryImpl implements CallbackApiBeanFactory {

  private final SpringUtils springUtils;

  @Override
  public Oauth2AceAuthenticationCallbackApi getOrCreateAuthCallbackApi(Oauth2RegisteredClientAuthConfig oauth2RegisteredClientAuthConfig) {

    Assert.isTrue(Oauth2RegisteredClientAuthConfigApiImplTypeEnum.BEAN.getCode().equals(oauth2RegisteredClientAuthConfig.getApiImplType()),
        "仅支持bean类型接口创建"
    );

    try {
      if (this.isDefaultCallbackApiConfig(oauth2RegisteredClientAuthConfig)) {
        return this.getOrCreateDefaultOauth2AceAuthCallbackApi();
      }
      Oauth2AceAuthenticationCallbackApi result = (Oauth2AceAuthenticationCallbackApi) springUtils
          .getDefaultListableBeanFactory()
          .getBean(oauth2RegisteredClientAuthConfig.getName());

      return result;
    } catch (Throwable ex) {
      throw new RuntimeException(String.format("获取[%s]类型 bean失败", Oauth2AceAuthenticationCallbackApi.class.getName()), ex);
    }
  }

  @Override
  public Oauth2AceAuthorizationCallbackApi getOrCreateUserInfoCallbackApi(Oauth2RegisteredClientAuthConfig oauth2RegisteredClientAuthConfig) {
    Assert.isTrue(Oauth2RegisteredClientAuthConfigApiImplTypeEnum.BEAN.getCode().equals(oauth2RegisteredClientAuthConfig.getApiImplType()),
        "仅支持bean类型接口创建"
    );

    try {
      if (this.isDefaultCallbackApiConfig(oauth2RegisteredClientAuthConfig)) {
        return this.getOrCreateDefaultOauth2AceUserInfoCallbackApi();
      }
      Oauth2AceAuthorizationCallbackApi result = (Oauth2AceAuthorizationCallbackApi) springUtils
          .getDefaultListableBeanFactory()
          .getBean(oauth2RegisteredClientAuthConfig.getName());

      return result;
    } catch (Throwable ex) {
      throw new RuntimeException(String.format("获取[%s]类型 bean失败", Oauth2AceAuthorizationCallbackApi.class.getName()), ex);
    }
  }


  private boolean isDefaultCallbackApiConfig(Oauth2RegisteredClientAuthConfig oauth2RegisteredClientAuthConfig) {
    return StringUtils.isBlank(oauth2RegisteredClientAuthConfig.getBeanName());
  }

  private Oauth2AceAuthenticationCallbackApi getOrCreateDefaultOauth2AceAuthCallbackApi() {
    return springUtils.getDefaultListableBeanFactory().getBean(Oauth2AceAuthenticationCallbackApi.class);
  }

  private Oauth2AceAuthorizationCallbackApi getOrCreateDefaultOauth2AceUserInfoCallbackApi() {
    return springUtils.getDefaultListableBeanFactory().getBean(Oauth2AceAuthorizationCallbackApi.class);
  }
}
